package order

import (
	"context"
	"fmt"

	goodspb "mxshop_srvs/goods_srv/proto/gen/v1"
	inventorypb "mxshop_srvs/inventory_srv/proto/gen/v1"
	"mxshop_srvs/order_srv/model"
)

// Manager defines an order manager.
type Manager struct {
	GoodsService     goodspb.GoodsClient
	InventoryService inventorypb.InventoryClient
}

// NewManager creates an order manager.
func NewManager(goodsClient goodspb.GoodsClient, inventoryClient inventorypb.InventoryClient) *Manager {
	return &Manager{
		GoodsService:     goodsClient,
		InventoryService: inventoryClient,
	}
}

func goodsInfoProtoToModel(goods *goodspb.GoodsInfoResponse) *model.OrderGoods {
	return &model.OrderGoods{
		GoodsID:    goods.Id,
		GoodsName:  goods.Name,
		GoodsImage: goods.GoodsFrontImage,
		GoodsPrice: goods.ShopPrice,
	}
}

// OrderHandling get amount of the order and deduct inventory.
func (m *Manager) OrderHandling(c context.Context, goodsIDs []int32, goodsNumsMap map[int32]int32) (int32, []*model.OrderGoods, error) {
	// 商品的价格自己查询 - 访问商品服务 (跨微服务)
	goods, err := m.GoodsService.BatchGetGoods(c, &goodspb.BatchGoodsIdInfo{Id: goodsIDs})
	if err != nil {
		return 0, nil, fmt.Errorf("cannot get goods: %v", err)
	}

	goodsDataLen := len(goods.Data)
	var orderAmount int32
	orderGoods := make([]*model.OrderGoods, 0, goodsDataLen)           // 定义需要批量插入OrderGoods表的内容
	goodsInvInfo := make([]*inventorypb.GoodsInvInfo, 0, goodsDataLen) // 定义调用库存服务的参数

	for _, goodsInfo := range goods.Data {
		// 每件商品购买总数
		goodsNums := goodsNumsMap[goodsInfo.Id]

		// 累加计算总金额
		orderAmount += goodsInfo.ShopPrice * goodsNums

		// 组装需要批量插入OrderGoods表的内容
		goodsIns := goodsInfoProtoToModel(goodsInfo)
		goodsIns.Nums = goodsNums
		orderGoods = append(orderGoods, goodsIns)

		// 组装需要批量扣减库存的内容
		goodsInvInfo = append(goodsInvInfo, &inventorypb.GoodsInvInfo{
			GoodsId: goodsInfo.Id,
			Num:     goodsNums,
		})
	}

	// 库存的扣减 - 访问库存服务 (跨微服务)
	_, err = m.InventoryService.Sell(context.Background(), &inventorypb.SellInfo{GoodsInfo: goodsInvInfo})
	if err != nil {
		return 0, nil, fmt.Errorf("cannot deducted inventory: %v", err)
	}

	return orderAmount, orderGoods, nil
}
